# !/usr/bin/python
# -*- coding=utf-8 -*-

import logging
from django.db import models
from django.db.models import fields

from . import admin_fields

logger = logging.getLogger(__name__)


class BaseAbstractVmodel(models.Model):
    class Meta(object):
        abstract = True

    def get_info(self, include=None, exclude=None):
        from utils import field_format
        dict_info = {}
        for field in self._meta.concrete_fields:
            if (exclude is not None) and (field.attname in exclude):
                continue

            if (include is not None) and (field.attname not in include):
                continue

            attname = field.attname
            val = getattr(self, field.attname)
            if isinstance(field, fields.CharField) or isinstance(field, fields.TextField):
                val = field_format.null_2_str(val)

            elif isinstance(field, fields.DateTimeField) or isinstance(field, fields.DateField) or \
                    isinstance(field, fields.TimeField):
                if val:
                    val = field_format.time_2_str(val)
            elif isinstance(field, fields.IntegerField) or isinstance(field, fields.FloatField) or \
                    isinstance(field, fields.PositiveIntegerField) or isinstance(field, fields.SmallIntegerField) or \
                    isinstance(field, fields.BigIntegerField):
                if field.null:
                    val = field_format.null_2_number(val, default=None)
                else:
                    val = field_format.null_2_number(val)

            elif isinstance(field, fields.related.ForeignKey):
                val = field_format.null_2_number(val)

            elif isinstance(field, fields.files.ImageField):
                val = field_format.url_2_str(val)

            elif isinstance(field, fields.files.FileField):
                val = field_format.url_2_str(val)

            dict_info[attname] = val

        return dict_info

    def db_2_sql(self, lst_sql=None, is_ignore=False):
        lst_field = []
        lst_value = []
        for field in self._meta.concrete_fields:
            lst_field.append("`%s`" % field.attname)
            val = getattr(self, field.attname)
            if isinstance(field, fields.CharField) or isinstance(field, fields.TextField):
                if val is None:
                    lst_value.append("null")
                else:
                    try:
                        import re
                        val = re.sub(r"\\n", r"\\\\n", val)
                        val = re.sub(r"\\r", r"\\\\r", val)
                        val = re.sub(r"\\'", r"\\\\'", val)
                        val = re.sub(r'\\"', r'\\\\"', val)
                        val = re.sub(r"\'", r"\\'", val)
                        val = re.sub(r'\"', r'\\"', val)
                        val = re.sub(r"\n", r"\\n", val)
                        val = re.sub(r"\r", r"\\r", val)
                        val = re.sub(r"\\x", r"\\\\x", val)
                    except (BaseException,):
                        pass
                    # val = val.replace("\n", "\\n").replace("\'", "\\'").replace("\r", "\\r'").replace('\"', '\\"').replace(r"\x", r"\\x")
                    # val = val.replace("'\\n", "'\\\\n").replace('"\\n', '"\\\\n').replace("\\r\'", "\\\\r\'").replace('\\r\"', '\\\\r\"')

                    try:
                        val.encode(encoding='gb2312')
                        lst_value.append('"%s"' % val)
                        # lst_value.append('"%s"' % val.replace("\r\n", "\n").replace("'", "\\'").replace('"', '\\"'))
                    except (BaseException,):
                        try:
                            val = val.encode(encoding='utf-8')
                        except (BaseException,):
                            pass
                        lst_value.append('"%s"' % val)
                        # lst_value.append('"%s"' % val.replace("\r\n", "\n").replace("'", "\\'").replace('"', '\\"').encode(encoding='utf-8'))
            elif isinstance(field, (fields.files.ImageField, fields.files.FileField)):
                try:
                    if val.url.find("/media/") == 0:
                        url = val.url[7:]
                    else:
                        url = val.url
                    lst_value.append('"%s"' % url)
                except (BaseException,):
                    lst_value.append('""')

            elif isinstance(field, fields.DateTimeField) or isinstance(field, fields.DateField) or \
                    isinstance(field, fields.TimeField):
                if val is None:
                    lst_value.append("null")
                else:
                    lst_value.append('"%s"' % val)

            else:
                if val is None:
                    lst_value.append("null")
                else:
                    lst_value.append(val)

        if is_ignore:
            sql = "insert ignore into %s(%s) values(%s);" % (
                self._meta.db_table, ",".join(lst_field), ("%s," * len(lst_field)).strip(","))
        else:
            sql = "insert into %s(%s) values(%s);" % (
                self._meta.db_table, ",".join(lst_field), ("%s," * len(lst_field)).strip(","))

        sql = sql % tuple(lst_value)
        if lst_sql is not None:
            lst_sql.append(sql)

        return sql

    def add_2_sql(self):
        lst_field = []
        lst_value = []
        for field in self._meta.concrete_fields:
            lst_field.append("`%s`" % field.attname)
            val = getattr(self, field.attname)
            if isinstance(field, fields.CharField) or isinstance(field, fields.TextField):
                if val is None:
                    lst_value.append("null")
                else:
                    try:
                        val.encode(encoding='gb2312')
                        lst_value.append('"%s"' % val)
                    except (BaseException,):
                        lst_value.append('"%s"' % val.encode(encoding='utf-8'))

            elif isinstance(field, fields.DateTimeField) or isinstance(field, fields.DateField) or \
                    isinstance(field, fields.TimeField):
                if val is None:
                    lst_value.append("null")
                else:
                    lst_value.append('"%s"' % val)

            else:
                if val is None:
                    lst_value.append("null")
                else:
                    lst_value.append(val)

        sql = "INSERT INTO `%s` (%s) values(%s);" % (
            self._meta.db_table, ",".join(lst_field), ("%s," * len(lst_field)).strip(","))
        sql = sql % tuple(lst_value)
        return sql

    def del_2_sql(self):
        sql = "DELETE FROM `%s` WHERE `%s`.`id`=%s;" % (self._meta.db_table, self._meta.db_table, getattr(self, "id"))
        return sql

    def update_2_sql(self):
        # lst_field = []
        lst_value = []
        for field in self._meta.concrete_fields:

            if field.attname == "id":
                continue

            field_name = "`%s`" % field.attname
            val = getattr(self, field.attname)
            if isinstance(field, fields.CharField) or isinstance(field, fields.TextField):
                if val is None:
                    value = "null"
                else:
                    try:
                        import re
                        val = re.sub(r"\\n", r"\\\\n", val)
                        val = re.sub(r"\\r", r"\\\\r", val)
                        val = re.sub(r"\\'", r"\\\\'", val)
                        val = re.sub(r'\\"', r'\\\\"', val)
                        val = re.sub(r"\'", r"\\'", val)
                        val = re.sub(r'\"', r'\\"', val)
                        val = re.sub(r"\n", r"\\n", val)
                        val = re.sub(r"\r", r"\\r", val)
                        value = re.sub(r"\\x", r"\\\\x", val)
                    except (BaseException,):
                        pass
                    # try:
                    #     value = val.encode(encoding='gb2312')
                    # except (BaseException,):
                    # value = value.encode(encoding='utf-8')
                    value = '"%s"' % value
            elif isinstance(field, fields.DateTimeField) or isinstance(field, fields.DateField) or \
                    isinstance(field, fields.TimeField):
                if val is None:
                    value = "null"
                else:
                    value = '"%s"' % val

            else:
                if val is None:
                    value = "null"
                else:
                    value = val

            lst_value.append("%s=%s" % (field_name, value))

        sql = "UPDATE `%s` SET %s WHERE `%s`.`id`=%s;" % (self._meta.db_table, ",".join(lst_value),
                                                          self._meta.db_table, getattr(self, "id"))
        return sql


class BaseVmodel(BaseAbstractVmodel):
    id = admin_fields.UuidField(max_length=16, primary_key=True, verbose_name="ID")
    create_time = models.DateTimeField(verbose_name=u"创建时间", auto_now_add=True)
    update_time = models.DateTimeField(verbose_name=u"修改时间", auto_now=True)
    del_flag = models.BooleanField(verbose_name=u"删除", default=False)
    order = models.IntegerField(verbose_name=u"排序", db_index=True, default=2147483647)

    class Meta:
        abstract = True


class BaseVmodelUuid32(BaseAbstractVmodel):
    id = admin_fields.UuidField(max_length=32, primary_key=True, verbose_name="ID")
    create_time = models.DateTimeField(verbose_name=u"创建时间", auto_now_add=True)
    update_time = models.DateTimeField(verbose_name=u"修改时间", auto_now=True)
    del_flag = models.BooleanField(verbose_name=u"删除", default=False)
    order = models.IntegerField(verbose_name=u"排序", db_index=True, default=2147483647)

    class Meta:
        abstract = True
